import {default as Wx, wx} from "./Wx";
import Toast from "../../app/popups/Toast";
import LocalStorage from "../utils/LocalStorage";
import {globalConfig} from "../../app/consts/GlobalConfig";
import CommonUtil from "../utils/CommonUtil";
import {logger} from "../../app/third-scripts/game_sdk/Logger";

export class ShareUtil {

    private lastOnShowTime: number = 0;
    // 分享内容提供者
    private shareContentProvider: ShareContentProvider = null;

    public setContentProvider(provider: ShareContentProvider) {
        this.shareContentProvider = provider;
    }

    public notifyOnShow() {
        cc.log("分享收到 onShow");
        this.lastOnShowTime = cc.sys.now()
    }

    /**
     * 初始化右上角的分享菜单.
     * @param {string} title
     * @param {string} imageUrl
     * @param query
     * @param {boolean} withTicket
     */
    public initShareMenu(query?: any, title?: string, imageUrl?: string, withTicket?: boolean) {
        if (!Wx.isWeChatEnv()) {
            return;
        }
        wx.showShareMenu({withShareTicket: true});
        let q = "";
        if (query) {
            for (const prop in query) {
                if (query.hasOwnProperty(prop)) {
                    q += `${prop}=${query[prop]}&`;
                }
            }
        }
        let text = title || (this.shareContentProvider && this.shareContentProvider.getText()) || "分享";
        let image = imageUrl || (this.shareContentProvider && this.shareContentProvider.getImage());
        logger.onShareAppMessage(() => {
            return {
                title: text,
                imageUrl: image,
                query: q,
            };
        });
    }

    public openCustomerService() {
        if (wx && wx.openCustomerServiceConversation) {
            wx.openCustomerServiceConversation()
        } else {
            Toast.showToast("微信版本较低，暂不支持此功能")
        }
    }

    /**
     * 去分享. 可携带若干特殊参数.
     *  @param query => {id:1,scene:2}
     * @param {string} title
     * @param {string} imageUrl
     * @returns {Promise<>}  ret 为群ticket.
     */
    public async share(query?: any, title?: string, imageUrl?: string): Promise<any> {

        if (!Wx.isWeChatEnv()) {
            return Promise.resolve(5);
        }

        // 禁止分享.
        if (!globalConfig.shareEnable) {
            return Promise.resolve(5);
        }

        wx.updateShareMenu({
            withShareTicket: true,
        });
        let q = "";
        if (query) {
            for (const i in query) {
                if (query.hasOwnProperty(i)) {
                    q += `${i}=${query[i]}&`;
                }
            }
        }

        cc.log("分享的参数:", q);

        let text = title || (this.shareContentProvider && this.shareContentProvider.getText()) || "分享";
        let image = imageUrl || (this.shareContentProvider && this.shareContentProvider.getImage());
        logger.shareAppMessage({
            title: text,
            imageUrl: image,
            query: q,
            success(res) {
                cc.log("分享结果:", res);
            },
            fail(res) {
            },
        });
        return this.checkShareEnd();
    }

    public async forceShare(query?: any, title?: string, imageUrl?: string) {
        if (!Wx.isWeChatEnv()) {
            return Promise.resolve();
        }
        wx.updateShareMenu({
            withShareTicket: true,
        });
        let q = "";
        if (query) {
            for (const i in query) {
                if (query.hasOwnProperty(i)) {
                    q += `${i}=${query[i]}&`;
                }
            }
        }
        cc.log("分享的参数:", q);
        let text = title || (this.shareContentProvider && this.shareContentProvider.getText()) || "分享";
        let image = imageUrl || (this.shareContentProvider && this.shareContentProvider.getImage());
        logger.shareAppMessage({
            title: text,
            imageUrl: image,
            query: q,
            success(res) {
                cc.log("分享结果:", res);
            },
            fail(res) {
            }
        });
        return this.checkShareEnd();
    }

    public async checkShareEnd(): Promise<number> {
        const onShareTime = this.lastOnShowTime = cc.sys.now();
        while (this.lastOnShowTime == onShareTime) {
            if (cc.sys.now() - onShareTime > 60000) {
                break;
            }
            await CommonUtil.delay(0.5);
        }
        return this.lastOnShowTime - onShareTime;
    }

    // 分享时判断跳转时长小于5秒认为是异常分享.
    public async shareResult(query?: any, title?: string, imageUrl?: string): Promise<boolean> {
        return this.share(query, title, imageUrl).then(time => {
            return Promise.resolve(time >= 2200);
        });
    }

    // 处理启动参数中包含的启动数据.
    public async procLaunchOption(callback: (shareTicket: string, scene: number, query: any, referrerInfo: any) => void) {
        if (Wx.isWeChatEnv()) {
            const launchOptions = wx.getLaunchOptionsSync();
            if (callback) {
                callback(launchOptions.shareTicket, launchOptions.scene, launchOptions.query, launchOptions.referrerInfo);
            }
        }
    }

    // 获取分享信息.
    public getShareInfo(shareTicket: string): Promise<any> {
        if (!Wx.isWeChatEnv()) {
            return;
        }
        return new Promise<any>(resolve => {
            wx.getShareInfo({
                shareTicket: shareTicket,
                success(ret) {
                    resolve(ret)
                },
                fail(ret) {
                    resolve(null);
                }
            })
        })
    }

    // 分享到群. 最终获得解密后的群ID.
    public shareWithGroup(params: any): Promise<{ group?: boolean, openGId?: string }> {

        return this.share(null, null, params).then(res => {
            // cc.log("shareWithGroup:", res);
            if (!res || !res.shareTickets) {
                return Promise.resolve({group: false})
            }
            return this.getShareInfo(res.shareTickets[0]).then(res => {
                cc.log("Wx.getShareInfo:", res);
                if (!res) {
                    return Promise.resolve({group: false});
                }
                if (this.shareContentProvider) {
                    return this.shareContentProvider.decryptGroupInfo(res.iv, res.encryptedData);
                }
                return Promise.resolve({});
            })
        }).catch(ret => {
            Toast.showToast("分享失败");
        })
    }

    /**
     * 分享到群,并判断是否需要分享到不同群.
     * 可根据filter 判断同名群分享是否有效.
     * @param scene
     * @param filter  返回true 表示要拦截过滤掉.
     */
    public async filterGroupShare(scene: string, filter: (group: ShareGroupInfo) => boolean): Promise<{ ret: Boolean, group: Boolean }> {
        return this.shareWithGroup({from: scene}).then(res => {
            if (res.group === false) {
                Toast.showToast("需要分享到群才能复活哦");
                return Promise.resolve({group: false, ret: false})
            }
            // cc.log("分享到群结果:", res);
            const gInfo = shareGroups.findGid(scene, res.openGId);
            if (!gInfo) {
                shareGroups.saveGid(scene, res.openGId);
                // cc.log("saveGid....");
            } else {
                if (filter && !filter(gInfo)) {
                    // cc.log("必须分享到不同的群才行哦");
                    Toast.showToast("需要分享到不同群才能复活哦");
                    return Promise.resolve({group: true, ret: false});
                } else {
                    // cc.log("filter 判定成功.");
                    shareGroups.saveGid(scene, res.openGId);
                }
            }
            return Promise.resolve({group: true, ret: true})
        });
    }
}

export const shareUtil: ShareUtil = new ShareUtil();

export class ShareGroupInfo {
    public scene: string;
    public gid: string;
    public ts: number;

    constructor(s, g, t) {
        this.scene = s;
        this.gid = g;
        this.ts = t;
    }
}

export class ShareGroups {
    private data: {
        [key: string]: {
            [key: string]: ShareGroupInfo;
        };
    } = {};

    public init() {
        this.data = LocalStorage.getObj("_share_groups", {});
    }

    public findGid(scene: string, gid: string): ShareGroupInfo {
        const d = this.data[scene];
        if (!d) {
            this.data[scene] = {};
            return null;
        }
        return d[gid];
    }

    public saveGid(scene: string, gid: string) {
        if (!this.data[scene]) {
            this.data[scene] = {};
        }
        this.data[scene][gid] = new ShareGroupInfo(scene, gid, cc.sys.now());
        LocalStorage.setObj("_share_groups", this.data);
    }

    // 获取分享到群的次数. 根据过滤条件进行筛选.
    public getSharedTimes(scene: string, filter: (g: ShareGroupInfo) => boolean): number {
        const shares = this.data[scene];
        if (!shares) {
            return 0;
        }
        if (!filter) {
            return Object.keys(shares).length;
        }
        let count = 0;
        for (let k in shares) {
            if (filter(shares[k])) {
                count++;
            }
        }
        return count;
    }

    public clearScene(scene: string) {
        delete this.data[scene];
        LocalStorage.setObj("_share_groups", this.data);
    }
}

export const shareGroups = new ShareGroups();
shareGroups.init();

export interface ShareContentProvider {

    // 获取分享文案.
    getText(): string;

    // 获取分享图片.
    getImage(): string;

    // 解密分享到的群信息.
    decryptGroupInfo(iv: string, encryptedData: string): Promise<any>;
}

const defContentProvider = {
    getText(): string {
        console.warn("请设置自己的分享数据");
        return "分享";
    },
    getImage(): string {
        return "";
    },
    decryptGroupInfo(iv: string, data: string): Promise<any> {
        return Promise.resolve({group: !!data});
    }
};
shareUtil.setContentProvider(defContentProvider);